#include "arg_parse.h"
#include <string.h>
#include <stdio.h>

typedef struct
{
    TYargsFunc func;
    char sname;
    char *name;
    void *def;
    size_t def_tam;
    int encontre;
    char *buf;
} TArg;

struct TYargs
{
    int c_max, c;
    TArg *args;
};

TYargs *Yargs_new(int c)
{
    TYargs *this = NULL;
    if (!c)
        return NULL;

    this = (TYargs *)calloc(1, sizeof(TYargs));
    this->c_max = c;

    this->args = (TArg *)calloc(c, sizeof(TArg));

    return this;
}

int Yargs_add_arg(TYargs *this, TYargsFunc func, char sname, char *name, void *defecto, size_t tam)
{
    int c = this->c;
    if (!this || c >= this->c_max)
        return 1;

    this->args[c].func = func;
    this->args[c].sname = sname;
    this->args[c].name = strcpy((char *)calloc(strlen(name) + 1, sizeof(char)), name);
    if (tam && defecto)
    {
        this->args[c].def = calloc(1, tam);
        memcpy(this->args[c].def, defecto, tam);
        this->args[c].def_tam = tam;
    }

    this->c++;
    return 0;
}

/**
 * 用sname获取Arg节点，未查到返回NULL
 */
TArg *get_arg_by_sname(TYargs *this, char c)
{
    int i = 0;
    for (i = 0; i < this->c; i++)
    {
        if (this->args[i].sname == c)
            return &(this->args[i]);
    }

    return NULL;
}

/**
 * 用name获取Arg节点，未查到返回NULL
 */
TArg *get_arg_by_name(TYargs *this, char *name)
{
    int i = 0;
    for (i = 0; i < this->c; i++)
    {
        if (strcmp(this->args[i].name, name) == 0)
            return &(this->args[i]);
    }
    return NULL;
}

int Yargs_parse(TYargs *this, int argc, char *argv[])
{
    int i = 0;
    if (!this)
        return 1;

    for (i = 1; i < argc; i++)
    {
        TArg *arg = NULL;
        if (argv[i][0] == '-')
        {
            if (argv[i][1] == '-')
                arg = get_arg_by_name(this, argv[i] + 2);
            else
                arg = get_arg_by_sname(this, argv[i][1]);

            if (!arg)
                continue;

            arg->encontre = 1;

            if (arg->func == NULL) // Es flag
                continue;

            if (i + 1 < argc)
            {
                i++;
                arg->buf = strcpy((char *)calloc(strlen(argv[i]) + 1, sizeof(char)), argv[i]);
            }
        }
    }

    return 0;
}

void *Yargs_get_arg(TYargs *this, char sname)
{
    if (!this)
        return NULL;

    TArg *arg = get_arg_by_sname(this, sname);

    if (!arg)
        return NULL;

    if (arg->encontre)
    {
        if (arg->func == NULL)
        {
            return (void *)1;
        }

        if (arg->buf == NULL)
            return NULL;

        return arg->func(arg->buf);
    }

    return arg->def;
}

int Yargs_delete(TYargs *this)
{
    int i = 0;
    if (!this)
        return 1;

    for (i = 0; i < this->c; i++)
    {
        if (this->args[i].name)
            free(this->args[i].name);
        if (this->args[i].def)
            free(this->args[i].def);
        if (this->args[i].buf)
            free(this->args[i].buf);
    }
    free(this->args);
    free(this);

    return 0;
}

void *Yargs_parse_str(char *str)
{
    return strcpy((char *)calloc(strlen(str) + 1, sizeof(char)), str);
}
